/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package semantic_network;


/**
 *
 * @author Hammad
 */
import file_handler.File_Manager;
import java.util.Vector;

public class Descriptor_Handler
{
    private SQL_Handler_Network sql_handler_1 = new SQL_Handler_Network();
    private SQL_Handler_Network sql_handler_2 = new SQL_Handler_Network();

    private Vector[] descriptors_array;
    private Vector[] descriptors_freq_array;

    File_Manager file_manager = new File_Manager();
    
    public Descriptor_Handler(SQL_Handler_Network sql_handler_1,SQL_Handler_Network sql_handler_2)
    {
        this.sql_handler_1 = sql_handler_1;
        this.sql_handler_2 = sql_handler_2;
    }


    /*
     * It extracts the desriptors and their frequencies when a given resource name is given
     */
    public void extract_descriptors(Vector<String> resources)
    {
        StringBuffer descriptors_statistics = new StringBuffer();

        sql_handler_1.connect_db();
        sql_handler_2.connect_db();

        descriptors_array = new Vector[resources.size()];
        descriptors_freq_array = new Vector[resources.size()];

        for (int i = 0; i < resources.size(); i++)
        {
            String resource = resources.elementAt(i).toString();

            Vector distinct_sen_ids = sql_handler_1.get_distinct_sen_ids_for_given_resource_name(resource);
            getDescriptors_array()[i] = sql_handler_2.get_descriptors_in_sentences(distinct_sen_ids);

            descriptors_statistics.append("\nNo of descriptors for resource " + resource + " is : " + getDescriptors_array()[i].size() + "\n");
            descriptors_statistics.append("\n  **************************************************" + "\n");
            descriptors_statistics.append("\n Value                                    Freq" + "\n");

            System.out.println("No of descriptors for resource " + resource + " is : " + getDescriptors_array()[i].size());
            System.out.println("  **************************************************");
            System.out.println("Value                                    Freq");

            descriptors_freq_array[i] = sql_handler_2.return_descriptors_freq();

            for (int j = 0; j < getDescriptors_array()[i].size(); j++)
            {
                System.out.println(getDescriptors_array()[i].elementAt(j).toString() + "        " + getDescriptors_freq_array()[i].elementAt(j).toString());
                descriptors_statistics.append("\n" + getDescriptors_array()[i].elementAt(j).toString() + "        " + getDescriptors_freq_array()[i].elementAt(j).toString());
            }
        }
        file_manager.fileWriter(descriptors_statistics.toString(), "Resources\\Descriptors\\Output\\Descriptors_stats.txt");
    }


    /*
     * Matches descriptors using exact values.
     * @param d1 First array of vector of descriptors
     * @param d2 Second array of vector of descriptors
     */
    public double match_descriptors(Vector<String> d1, Vector<String> d2)
    {
        double similarity = 0.0;
        try {
            for (String descriptor1 : d1)
            {
                for (String descriptor2 : d2)
                {
                    if (descriptor1.toLowerCase().equals(descriptor2.toLowerCase()))
                    {
                        similarity = similarity + 1;
                    }
                }
            }
        }
        catch (Exception ex)
        {
            System.out.println("Exception in matching descriptors considering "
                    + "inverse descriptor frequency : " + ex.getMessage());
        }
        return similarity;
    }

        /**
     * Measures similarity measure between two vectors (of descriptors) using lexical profiles
     * of descriptors
     * @param d1
     * @param d2
     * @return
     */
    public double match_descriptors_using_lexical_profiles(Vector<String> d1, Vector<String> d2,String similarity_metric)
    {
        Vector_Manipulation vector_builder = new Vector_Manipulation();
        
        double cosine = 0.0;
        double dice = 0.0;

        for (String descriptor1 : d1)
        {
            double similarity = 0.0;

            for (String descriptor2 : d2)
            {
                Vector<String> profile1 = vector_builder.make_term_profile(descriptor1);
                Vector<String> profile2 = vector_builder.make_term_profile(descriptor2);

                int size1 = profile1.size();
                int size2 = profile2.size();

                profile1.retainAll(profile2);


                if (similarity_metric.equals("COSINE"))
                {
                    similarity = (double) (profile1.size()) / (size1*size2);
                    cosine = cosine + similarity;
                }
                else if (similarity_metric.equals("DICE"))
                {
                    similarity = (double) (2 * profile1.size()) / (size1 + size2);
                    dice = dice + similarity;
                }
            }
        }

        if (similarity_metric.equals("COSINE"))
            return cosine;
        else
            return dice;
    }

        /**
     * Measures similarity between descriptors on basis of the lexical profiles of sharing descriptors.
     * It uses tf*idf while meausring inner product.
     * This method corresponds to the "Method3" of JBS paper
     * @param d1
     * @param tfidf1
     * @param d2
     * @param tfidf2
     * @return
     */
    public double match_descriptors_using_idf_of_lexical_profiles(Vector<String> d1, Vector tfidf1, Vector<String> d2, Vector tfidf2)
    {
        Vector_Manipulation vector_builder = new Vector_Manipulation();
        
        double commulative_tf_idf = 0.0;
        try
        {
            for (int i = 0; i < d1.size(); i++)
            {
                String descriptor1 = d1.elementAt(i).toString();

                for (int j = 0; j < d2.size(); j++)
                {
                    String descriptor2 = d2.elementAt(j).toString();

                    Vector<String> profile1 = vector_builder.make_term_profile(descriptor1);
                    Vector<String> profile2 = vector_builder.make_term_profile(descriptor2);

                    int size1 = profile1.size();
                    int size2 = profile2.size();

                    profile1.retainAll(profile2);

                    if (profile1.size()> 0 )
                    {
                        double temp1 = Double.parseDouble(tfidf1.elementAt(i).toString());
                        double temp2 = Double.parseDouble(tfidf2.elementAt(j).toString());
                        double temp3 = (double) profile1.size()/(size1*size2);
                        double local_tf_rdf = temp1 * temp2 * temp3;
                        commulative_tf_idf = commulative_tf_idf + local_tf_rdf;
                    }
                }
            }
        }
        catch (Exception ex)
        {
            System.out.println("Exception in matching descriptors considering their lexical profiles" +
                    "using inverse descriptor frequency : " + ex.getMessage());

        }
        return commulative_tf_idf;
    }

    /**
     * Measures similarity between resources on basis of sharing descriptors.
     * It uses tf*idf while meausring inner product
     * @param d1
     * @param tfidf1
     * @param d2
     * @param tfidf2
     * @return
     */
    public double match_descriptors_using_idf(Vector<String> d1, Vector tfidf1, Vector<String> d2, Vector tfidf2)
    {
        double commulative_tf_idf = 0.0;
        try
        {
            for (int i = 0; i < d1.size(); i++)
            {
                String descriptor1 = d1.elementAt(i).toString();
                for (int j = 0; j < d2.size(); j++)
                {
                    String descriptor2 = d2.elementAt(j).toString();

                    if (descriptor1.toLowerCase().equals(descriptor2.toLowerCase()))
                    {
                        double temp1 = Double.parseDouble(tfidf1.elementAt(i).toString());
                        double temp2 = Double.parseDouble(tfidf2.elementAt(j).toString());
                        double local_tf_rdf = temp1 * temp2;
                        commulative_tf_idf = commulative_tf_idf + local_tf_rdf;
                    }
                }
            }
        }
        catch (Exception ex)
        {
            System.out.println("Exception in matching descriptors considering " +
                    "inverse descriptor frequency : " + ex.getMessage());
        }
        return commulative_tf_idf;
    }


    /**
     * Measures the tf*idf of descriptors, given the descriptors, the frequency of descriptors
     * for a particular resource, and the commulative frequency of descriptor with all resources
     * @param descrs String value of all descriptors
     * @param desc_freqs Frequency of all descriptors for a given resource
     * @param sum_of_all_descriptors_frequencies_for_given_resource Sum of all descriptors' frequencies for a given resource
     */
    public Vector calculate_tf_idf(Vector descrs, Vector desc_freqs, int sum_of_all_descriptors_frequencies_for_given_resource,int number_of_resources)
    {
        Vector_Manipulation vector_builder = new Vector_Manipulation();
        Vector tf_idf = new Vector();
        
        try
        {
            for (int i = 0; i < descrs.size(); i++)
            {
                String desc_freq_str = desc_freqs.elementAt(i).toString().trim();
                int desc_freq = Integer.parseInt(desc_freq_str);
                double tf_descriptor_resource = (double) (desc_freq) / (sum_of_all_descriptors_frequencies_for_given_resource);

                /*
                 * The following code measures how many resources have this given descriptors
                 */
                int no_of_res_with_desc = 0;
                String descriptor = descrs.elementAt(i).toString();

                for (int j = 0; j < descriptors_array.length; j++)
                {
                    Vector local_descriptors_array = vector_builder.vector_assigner(descriptors_array[j].toString());
                    if (local_descriptors_array.contains(descriptor))
                    {
                        //TODO: Check if this is working correctly
                        no_of_res_with_desc++;
                    }
                }

                double denominator = (double) number_of_resources / (no_of_res_with_desc);
                double idf_descriptor_resource = Math.log(denominator);
                tf_idf.add(tf_descriptor_resource * idf_descriptor_resource);
            }
        }
        catch(Exception ex)
        {
            System.out.println("Exception thrown while calculating tf_idf: " + ex.getMessage());

        }

        return tf_idf;
    }



    /**
     * @return the descriptors_array
     */
    public Vector[] getDescriptors_array()
    {
        return descriptors_array;
    }

    /**
     * @param descriptors_array the descriptors_array to set
     */
    public void setDescriptors_array(Vector[] descriptors_array)
    {
        this.descriptors_array = descriptors_array;
    }

    /**
     * @return the descriptors_freq_array
     */
    public Vector[] getDescriptors_freq_array()
    {
        return descriptors_freq_array;
    }

    /**
     * @param descriptors_freq_array the descriptors_freq_array to set
     */
    public void setDescriptors_freq_array(Vector[] descriptors_freq_array)
    {
        this.descriptors_freq_array = descriptors_freq_array;
    }


}
